package com.gz.moreaseManager.utils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 日期、时间工具类
 */
public class DateUtil {

	private static final Log logger = LogFactory.getLog(DateUtil.class);

	private DateUtil() {
		/**
		 * 构造函数，禁止实例化
		 */
	}

	public enum DateFormat {
		/**
		 * 时间格式 yyyy-MM-dd
		 */
		DATE("yyyy-MM-dd"),
		/***
		 * 时间格式  HH:mm:ss
		 */
		TIME(" HH:mm:ss"),
		/**
		 * 时间格式 yyyy/MM/dd
		 */
		DATE_SLASH("yyyy/MM/dd"),
		/**
		 * 时间格式 yyyy-MM-dd HH:mm:ss
		 */
		DATE_TIME("yyyy-MM-dd HH:mm:ss");

		private final String val;

		DateFormat(String val) {
			this.val = val;
		}

		public String getVal() {
			return val;
		}
	}

	/**
	 * 获取DATE开始时间
	 *
	 * @param date 时间
	 * @param type 类型Calendar-specific value
	 * @return 开始时间
	 */
	public static Date getStartTime(Date date, Integer type) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		switch (type) {
			case Calendar.YEAR:
				calendar.set(Calendar.MONTH, 0);
				calendar.set(Calendar.DAY_OF_MONTH, 1);
				calendar.set(Calendar.HOUR_OF_DAY, 0);
				break;
			case Calendar.MONTH:
				calendar.set(Calendar.DAY_OF_MONTH, 1);
				calendar.set(Calendar.HOUR_OF_DAY, 0);
				break;
			case Calendar.DAY_OF_MONTH:
				calendar.set(Calendar.HOUR_OF_DAY, 0);
				break;
			default:
				break;
		}
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取DATE结束时间
	 *
	 * @param date 时间
	 * @param type 类型Calendar-specific value
	 * @return 结束时间
	 */
	public static Date getEndTime(Date date, Integer type) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		switch (type) {
			case Calendar.YEAR:
				calendar.set(Calendar.MONTH, calendar.getActualMaximum(Calendar.MONTH));
				calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH) - 1);
				calendar.set(Calendar.HOUR_OF_DAY, 23);
				break;
			case Calendar.MONTH:
				calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH) - 1);
				calendar.set(Calendar.HOUR_OF_DAY, 23);
				break;
			case Calendar.DAY_OF_MONTH:
				calendar.set(Calendar.HOUR_OF_DAY, 23);
				break;
			default:
				return null;
		}
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar.getTime();
	}

	/**
	 * DATE添加时间
	 *
	 * @param date 原时间
	 * @param nums 添加时间
	 * @param type 添加类型Calendar-specific value
	 * @return 时间对象
	 */
	public static Date addTime(Date date, int nums, Integer type) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(type, nums);
		return calendar.getTime();
	}

	/**
	 * 日期格式判断
	 *
	 * @param date   日期字符串
	 * @param format 字符串类型
	 * @return 是否日期格式
	 */
	public static boolean isDate(String date, DateFormat format) {
		boolean result = false;
		if (UtilTool.isBlank(date)) return false;
		SimpleDateFormat sdf;
		if (format.getClass() == DateFormat.class)
			sdf = new SimpleDateFormat(format.val);
		else
			sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			sdf.parse(date);
			result = true;
		} catch (ParseException e) {
			logger.warn("日期格式不合法", e);
		}
		return result;
	}

	/**
	 * 日期格式正则判断
	 *
	 * @param date  日期字符串
	 * @param regEx 正则表达式
	 * @return 是否日期格式
	 */
	public static boolean isFormatDate(String date, String regEx) {
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(date);
		return m.find();
	}

	/**
	 * 时间字符串转换
	 *
	 * @param dateStr 时间字符串
	 * @return 时间对象
	 * @throws ParseException 转换异常
	 */
	public static Date parseDate(String dateStr) throws ParseException {
		if (dateStr.indexOf("/") == 4) {
			return new SimpleDateFormat("yyyy/MM/dd").parse(dateStr);
		} else if (dateStr.indexOf("-") == 4) {
			return new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
		} else if (dateStr.indexOf("年") == 4) {
			return new SimpleDateFormat("yyyy年MM月dd").parse(dateStr);
		} else if (dateStr.length() == 8) {
			return new SimpleDateFormat("yyyyMMdd").parse(dateStr);
		} else {
			return new Date();
		}
	}

	/**
	 * 时间字符串转换
	 *
	 * @param dateStr 时间字符串
	 * @param format  时间格式
	 * @return 时间对象
	 */
	public static Date formatDate(String dateStr, DateFormat format) {
		if (!isDate(dateStr, format))
			return null;
		SimpleDateFormat sdf = new SimpleDateFormat(format.val);
		Date date = null;
		try {
			date = sdf.parse(dateStr);
		} catch (ParseException e) {
			logger.error("时间字符串转换异常", e);
		}
		return date;
	}

	/**
	 * 将毫秒换算成(天时分秒)
	 *
	 * @param ms 毫秒数据
	 * @return 中文时间字符串
	 */
	public static String formatTime(long ms) {
		Integer ss = 1000;
		Integer mi = ss * 60;
		Integer hh = mi * 60;
		Integer dd = hh * 24;
		long day = ms / dd;
		long hour = (ms - day * dd) / hh;
		long minute = (ms - day * dd - hour * hh) / mi;
		long second = (ms - day * dd - hour * hh - minute * mi) / ss;
		StringBuilder dateStr = new StringBuilder();
		if (day > 0) {
			dateStr.append(day).append("天");
		}
		if (hour > 0) {
			dateStr.append(hour).append("小时");
		}
		if (minute > 0) {
			dateStr.append(minute).append("分");
		}
		if (second > 0) {
			dateStr.append(second).append("秒");
		}
		return dateStr.toString();
	}

	/**
	 * 时间转字符串
	 *
	 * @param date   时间格式
	 * @param format 转换格式
	 * @return 时间字符串
	 */
	public static String dateToStr(Date date, String format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(date);
	}

	/**
	 * 时间转字符串
	 *
	 * @param date   时间格式
	 * @param format 转换格式
	 * @return 时间字符串
	 */
	public static String dateToStr(Date date, DateFormat format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format.val);
		return sdf.format(date);
	}

	/**
	 * 计算两个日期之间相差的天数
	 *
	 * @param smdate 较小的时间
	 * @param bdate  较大的时间
	 * @return 相差天数
	 * @throws ParseException 转换异常
	 */
	public static int getDaysBetween(Date smdate, Date bdate) throws ParseException {
		SimpleDateFormat dateFormat = new SimpleDateFormat(DateFormat.DATE.val);
		smdate = dateFormat.parse(dateFormat.format(smdate));
		bdate = dateFormat.parse(dateFormat.format(bdate));
		Calendar cal = Calendar.getInstance();
		cal.setTime(smdate);
		long time1 = cal.getTimeInMillis();
		cal.setTime(bdate);
		long time2 = cal.getTimeInMillis();
		long betweenDays = (time2 - time1) / (1000 * 3600 * 24);
		return Integer.parseInt(String.valueOf(betweenDays));
	}

	/**
	 * 获取两个日期相差的月数
	 *
	 * @param date1   时间1
	 * @param date2   时间2
	 * @param roundUP true:不够一个月按一个月算，false:不够一个月忽略
	 * @return 相差月数
	 */
	public static int getMonthsBetween(Date date1, Date date2, Boolean roundUP) {
		int result = 0;
		Date dateBefore = date1.before(date2) ? date1 : date2;
		Date dateAfter = date2.after(date1) ? date2 : date1;
		Date tempDate = dateBefore;
		do {
			tempDate = addTime(tempDate, 1, Calendar.DAY_OF_MONTH);
			if (roundUP != null && roundUP) {
				result++;
			} else {
				if (tempDate.before(dateAfter) || tempDate.compareTo(dateAfter) == 0) {
					result++;
				}
			}
		} while (tempDate.before(dateAfter));
		return result;
	}

	/**
	 * 获取当前日期是星期几
	 *
	 * @param dt 时间参数
	 * @return 当前日期是星期几
	 */
	public static int getWeekOfDate(Date dt) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(dt);
		int w = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		if (w < 0) w = 0;
		return w;
	}

	/**
	 * 日期(yyyy-MM-dd)和时间(HH:mm:ss)相加
	 *
	 * @param calendar 日期(yyyy-MM-dd)
	 * @param timeDate 时间(HH:mm:ss)
	 * @return 相加后的时间
	 */
	public static Date appendCalendarAndTime(Date calendar, Date timeDate) {
		Calendar cal_one = Calendar.getInstance();
		Calendar cal_two = Calendar.getInstance();
		cal_one.setTime(calendar);
		cal_two.setTime(timeDate);
		cal_one.add(Calendar.HOUR_OF_DAY, cal_two.get(Calendar.HOUR_OF_DAY));
		cal_one.add(Calendar.MINUTE, cal_two.get(Calendar.MINUTE));
		cal_one.add(Calendar.SECOND, cal_two.get(Calendar.SECOND));
		cal_one.add(Calendar.MILLISECOND, cal_two.get(Calendar.MILLISECOND));
		return cal_one.getTime();
	}

	/**
	 * 日期添加年
	 * @param date
	 * @param amount
	 * @return
	 */
	public static Date addYears(Date date, int amount)
	{
		return add(date, 1, amount);
	}

	public static Date addMonths(Date date, int amount)
	{
		return add(date, 2, amount);
	}

	public static Date addWeeks(Date date, int amount)
	{
		return add(date, 3, amount);
	}

	public static Date addDays(Date date, int amount)
	{
		return add(date, 5, amount);
	}

	public static Date addHours(Date date, int amount)
	{
		return add(date, 11, amount);
	}

	public static Date addMinutes(Date date, int amount)
	{
		return add(date, 12, amount);
	}

	public static Date addSeconds(Date date, int amount)
	{
		return add(date, 13, amount);
	}

	public static Date addMilliseconds(Date date, int amount)
	{
		return add(date, 14, amount);
	}

	private static Date add(Date date, int calendarField, int amount)
	{
		if(date == null)
		{
			throw new IllegalArgumentException("The date must not be null");
		} else
		{
			Calendar c = Calendar.getInstance();
			c.setTime(date);
			c.add(calendarField, amount);
			return c.getTime();
		}
	}
}